using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;

namespace CKY.AgentPlatform.RateLimiting
{
    /// <summary>
    /// 限流选项
    /// </summary>
    public class RateLimitOptions
    {
        public bool EnableRateLimiting { get; set; } = true;
        public int MaxRequests { get; set; } = 100;
        public int WindowMinutes { get; set; } = 15;
        public int QueueLimit { get; set; } = 0;
        public bool EnableApiKeyAuth { get; set; } = false;
        public string ApiKeyHeaderName { get; set; } = "X-API-Key";
        public string ApiKeyQueryParam { get; set; } = "api_key";
        public List<string> ValidApiKeys { get; set; } = new List<string>();
        public List<string> IPWhitelist { get; set; } = new List<string>();
        public List<string> UserWhitelist { get; set; } = new List<string>();
        public List<string> PathWhitelist { get; set; } = new List<string>();
        public bool EnableLogging { get; set; } = true;
        public bool EnableStatistics { get; set; } = true;
        public int CleanupIntervalMinutes { get; set; } = 60;
    }

    /// <summary>
    /// 限流统计服务
    /// </summary>
    public class RateLimitStatisticsService : ITransientDependency
    {
        private readonly DistributedCacheService _cacheService;
        private readonly RateLimitOptions _options;
        private readonly ILogger<RateLimitStatisticsService> _logger;

        public RateLimitStatisticsService(
            DistributedCacheService cacheService,
            IOptions<RateLimitOptions> options,
            ILogger<RateLimitStatisticsService> logger)
        {
            _cacheService = cacheService;
            _options = options.Value;
            _logger = logger;
        }

        /// <summary>
        /// 获取限流统计信息
        /// </summary>
        public async Task<RateLimitStatistics> GetStatisticsAsync()
        {
            var statistics = new RateLimitStatistics
            {
                Timestamp = DateTime.UtcNow,
                TotalRequests = await GetTotalRequestsAsync(),
                BlockedRequests = await GetBlockedRequestsAsync(),
                ActiveClients = await GetActiveClientsAsync(),
                TopBlockedClients = await GetTopBlockedClientsAsync(),
                TopEndpoints = await GetTopEndpointsAsync(),
                ResponseTimeAverage = await GetAverageResponseTimeAsync()
            };

            return statistics;
        }

        /// <summary>
        /// 获取客户端限流统计
        /// </summary>
        public async Task<ClientRateLimitStatistics> GetClientStatisticsAsync(string clientIdentifier)
        {
            var stats = new ClientRateLimitStatistics
            {
                ClientIdentifier = clientIdentifier,
                Timestamp = DateTime.UtcNow,
                TotalRequests = await GetClientRequestsAsync(clientIdentifier),
                BlockedRequests = await GetClientBlockedRequestsAsync(clientIdentifier),
                CurrentLimit = await GetClientCurrentLimitAsync(clientIdentifier),
                Endpoints = await GetClientEndpointsAsync(clientIdentifier)
            };

            return stats;
        }

        /// <summary>
        /// 清理过期统计数据
        /// </summary>
        public async Task CleanupExpiredStatisticsAsync()
        {
            try
            {
                var cutoffDate = DateTime.UtcNow.AddDays(-7); // 保留7天的统计数据
                
                // 清理过期的统计数据
                await CleanupExpiredKeysAsync(cutoffDate);
                
                _logger.LogInformation("限流统计数据清理完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清理限流统计数据失败");
            }
        }

        /// <summary>
        /// 重置客户端限流计数器
        /// </summary>
        public async Task ResetClientRateLimitAsync(string clientIdentifier)
        {
            try
            {
                var keys = await GetClientKeysAsync(clientIdentifier);
                foreach (var key in keys)
                {
                    await _cacheService.RemoveAsync(key);
                }

                _logger.LogInformation("重置客户端限流计数器: {ClientIdentifier}", clientIdentifier);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "重置客户端限流计数器失败: {ClientIdentifier}", clientIdentifier);
            }
        }

        /// <summary>
        /// 添加到IP白名单
        /// </summary>
        public async Task AddToIpWhitelistAsync(string ipAddress)
        {
            try
            {
                var whitelistKey = "rate_limit:config:ip_whitelist";
                var currentWhitelist = await _cacheService.GetAsync<List<string>>(whitelistKey) ?? new List<string>();
                
                if (!currentWhitelist.Contains(ipAddress))
                {
                    currentWhitelist.Add(ipAddress);
                    await _cacheService.SetAsync(whitelistKey, currentWhitelist, TimeSpan.FromDays(30));
                    
                    _logger.LogInformation("添加IP到白名单: {IpAddress}", ipAddress);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "添加IP到白名单失败: {IpAddress}", ipAddress);
            }
        }

        /// <summary>
        /// 从IP白名单中移除
        /// </summary>
        public async Task RemoveFromIpWhitelistAsync(string ipAddress)
        {
            try
            {
                var whitelistKey = "rate_limit:config:ip_whitelist";
                var currentWhitelist = await _cacheService.GetAsync<List<string>>(whitelistKey) ?? new List<string>();
                
                if (currentWhitelist.Contains(ipAddress))
                {
                    currentWhitelist.Remove(ipAddress);
                    await _cacheService.SetAsync(whitelistKey, currentWhitelist, TimeSpan.FromDays(30));
                    
                    _logger.LogInformation("从IP白名单中移除: {IpAddress}", ipAddress);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "从IP白名单中移除失败: {IpAddress}", ipAddress);
            }
        }

        /// <summary>
        /// 记录限流事件
        /// </summary>
        public async Task LogRateLimitEventAsync(RateLimitEvent rateLimitEvent)
        {
            try
            {
                var eventKey = $"rate_limit:event:{DateTime.UtcNow:yyyy-MM-dd}";
                var events = await _cacheService.GetAsync<List<RateLimitEvent>>(eventKey) ?? new List<RateLimitEvent>();
                
                events.Add(rateLimitEvent);
                
                // 限制事件数量，避免缓存过大
                if (events.Count > 1000)
                {
                    events = events.Skip(events.Count - 1000).ToList();
                }
                
                await _cacheService.SetAsync(eventKey, events, TimeSpan.FromDays(7));
                
                _logger.LogDebug("记录限流事件: {ClientIdentifier}, 端点: {EndpointKey}", 
                    rateLimitEvent.ClientIdentifier, rateLimitEvent.EndpointKey);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录限流事件失败");
            }
        }

        /// <summary>
        /// 获取限流事件
        /// </summary>
        public async Task<List<RateLimitEvent>> GetRateLimitEventsAsync(DateTime? startDate = null, DateTime? endDate = null)
        {
            try
            {
                var events = new List<RateLimitEvent>();
                var currentDate = startDate ?? DateTime.UtcNow.AddDays(-1);
                var endCurrentDate = endDate ?? DateTime.UtcNow;

                while (currentDate <= endCurrentDate)
                {
                    var eventKey = $"rate_limit:event:{currentDate:yyyy-MM-dd}";
                    var dayEvents = await _cacheService.GetAsync<List<RateLimitEvent>>(eventKey) ?? new List<RateLimitEvent>();
                    
                    events.AddRange(dayEvents.Where(e => e.Timestamp >= currentDate && e.Timestamp <= endCurrentDate));
                    currentDate = currentDate.AddDays(1);
                }

                return events.OrderByDescending(e => e.Timestamp).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取限流事件失败");
                return new List<RateLimitEvent>();
            }
        }

        private async Task<long> GetTotalRequestsAsync()
        {
            var today = DateTime.UtcNow.ToString("yyyy-MM-dd");
            var statsKey = $"rate_limit:stats:{today}";
            return await _cacheService.GetLongAsync(statsKey);
        }

        private async Task<long> GetBlockedRequestsAsync()
        {
            var today = DateTime.UtcNow.ToString("yyyy-MM-dd");
            var blockedKey = $"rate_limit:blocked:{today}";
            return await _cacheService.GetLongAsync(blockedKey);
        }

        private async Task<int> GetActiveClientsAsync()
        {
            var activeKey = $"rate_limit:active:{DateTime.UtcNow:yyyy-MM-dd-HH}";
            return (int)await _cacheService.GetLongAsync(activeKey);
        }

        private async Task<List<ClientStatistic>> GetTopBlockedClientsAsync()
        {
            var blockedKey = $"rate_limit:top_blocked:{DateTime.UtcNow:yyyy-MM-dd}";
            return await _cacheService.GetAsync<List<ClientStatistic>>(blockedKey) ?? new List<ClientStatistic>();
        }

        private async Task<List<EndpointStatistic>> GetTopEndpointsAsync()
        {
            var endpointsKey = $"rate_limit:top_endpoints:{DateTime.UtcNow:yyyy-MM-dd}";
            return await _cacheService.GetAsync<List<EndpointStatistic>>(endpointsKey) ?? new List<EndpointStatistic>();
        }

        private async Task<double> GetAverageResponseTimeAsync()
        {
            var responseTimeKey = $"rate_limit:response_time:{DateTime.UtcNow:yyyy-MM-dd}";
            return await _cacheService.GetDoubleAsync(responseTimeKey);
        }

        private async Task<long> GetClientRequestsAsync(string clientIdentifier)
        {
            var clientKey = $"rate_limit:client_requests:{clientIdentifier}:{DateTime.UtcNow:yyyy-MM-dd}";
            return await _cacheService.GetLongAsync(clientKey);
        }

        private async Task<long> GetClientBlockedRequestsAsync(string clientIdentifier)
        {
            var clientBlockedKey = $"rate_limit:client_blocked:{clientIdentifier}:{DateTime.UtcNow:yyyy-MM-dd}";
            return await _cacheService.GetLongAsync(clientBlockedKey);
        }

        private async Task<int> GetClientCurrentLimitAsync(string clientIdentifier)
        {
            var limitKey = $"rate_limit:{clientIdentifier}:global";
            var currentCount = await _cacheService.GetLongAsync(limitKey);
            return (int)currentCount;
        }

        private async Task<List<string>> GetClientEndpointsAsync(string clientIdentifier)
        {
            var endpointsKey = $"rate_limit:client_endpoints:{clientIdentifier}:{DateTime.UtcNow:yyyy-MM-dd}";
            return await _cacheService.GetAsync<List<string>>(endpointsKey) ?? new List<string>();
        }

        private async Task<List<string>> GetClientKeysAsync(string clientIdentifier)
        {
            // 简化实现，实际项目中需要更复杂的键匹配逻辑
            return new List<string>
            {
                $"rate_limit:{clientIdentifier}:global",
                $"rate_limit:{clientIdentifier}:stats",
                $"rate_limit:{clientIdentifier}:blocked"
            };
        }

        private async Task CleanupExpiredKeysAsync(DateTime cutoffDate)
        {
            // 简化实现，实际项目中需要遍历所有键并清理过期键
            var cleanupKey = $"rate_limit:last_cleanup:{DateTime.UtcNow:yyyy-MM-dd}";
            await _cacheService.SetAsync(cleanupKey, DateTime.UtcNow, TimeSpan.FromDays(1));
        }
    }

    /// <summary>
    /// 限流统计信息
    /// </summary>
    public class RateLimitStatistics
    {
        public DateTime Timestamp { get; set; }
        public long TotalRequests { get; set; }
        public long BlockedRequests { get; set; }
        public int ActiveClients { get; set; }
        public List<ClientStatistic> TopBlockedClients { get; set; }
        public List<EndpointStatistic> TopEndpoints { get; set; }
        public double ResponseTimeAverage { get; set; }

        public double BlockRate => TotalRequests > 0 ? (double)BlockedRequests / TotalRequests * 100 : 0;
    }

    /// <summary>
    /// 客户端限流统计
    /// </summary>
    public class ClientRateLimitStatistics
    {
        public string ClientIdentifier { get; set; }
        public DateTime Timestamp { get; set; }
        public long TotalRequests { get; set; }
        public long BlockedRequests { get; set; }
        public int CurrentLimit { get; set; }
        public List<string> Endpoints { get; set; }
        public double BlockRate => TotalRequests > 0 ? (double)BlockedRequests / TotalRequests * 100 : 0;
    }

    /// <summary>
    /// 客户端统计
    /// </summary>
    public class ClientStatistic
    {
        public string ClientIdentifier { get; set; }
        public long RequestCount { get; set; }
        public long BlockedCount { get; set; }
        public DateTime LastRequest { get; set; }
    }

    /// <summary>
    /// 端点统计
    /// </summary>
    public class EndpointStatistic
    {
        public string EndpointKey { get; set; }
        public long RequestCount { get; set; }
        public long BlockedCount { get; set; }
        public double AverageResponseTime { get; set; }
    }

    /// <summary>
    /// 限流事件
    /// </summary>
    public class RateLimitEvent
    {
        public DateTime Timestamp { get; set; }
        public string ClientIdentifier { get; set; }
        public string EndpointKey { get; set; }
        public string Action { get; set; }
        public string Reason { get; set; }
        public string IpAddress { get; set; }
        public string UserAgent { get; set; }
    }

    /// <summary>
    /// 限流后台服务
    /// </summary>
    public class RateLimitBackgroundService : Microsoft.Extensions.Hosting.BackgroundService
    {
        private readonly RateLimitStatisticsService _statisticsService;
        private readonly ILogger<RateLimitBackgroundService> _logger;
        private readonly RateLimitOptions _options;

        public RateLimitBackgroundService(
            RateLimitStatisticsService statisticsService,
            ILogger<RateLimitBackgroundService> logger,
            IOptions<RateLimitOptions> options)
        {
            _statisticsService = statisticsService;
            _logger = logger;
            _options = options.Value;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("限流后台服务启动");

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    await PerformMaintenanceTasksAsync(stoppingToken);
                    await Task.Delay(TimeSpan.FromMinutes(_options.CleanupIntervalMinutes), stoppingToken);
                }
                catch (OperationCanceledException)
                {
                    // 正常退出
                    break;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "限流后台服务执行失败");
                    await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
                }
            }

            _logger.LogInformation("限流后台服务停止");
        }

        private async Task PerformMaintenanceTasksAsync(CancellationToken stoppingToken)
        {
            try
            {
                // 清理过期统计数据
                await _statisticsService.CleanupExpiredStatisticsAsync();

                // 更新统计信息
                await UpdateStatisticsAsync();

                _logger.LogDebug("限流维护任务完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "限流维护任务失败");
            }
        }

        private async Task UpdateStatisticsAsync()
        {
            try
            {
                var stats = await _statisticsService.GetStatisticsAsync();
                
                // 缓存统计信息
                var statsKey = $"rate_limit:current_stats";
                await _statisticsService.GetType().GetMethod("SetAsync")?.Invoke(null, new object[] { statsKey, stats, TimeSpan.FromMinutes(15) });
                
                _logger.LogDebug("限流统计信息更新完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新限流统计信息失败");
            }
        }
    }
}